//
//  HJSQLDataTool.m
//  HJSQLDataTool_Example
//
//  Created by sky on 2019/11/22.
//  Copyright © 2019 hongjiang. All rights reserved.
//

#import "HJSQLDataTool.h"
//#import "XMGModelProtocol.h"
#import <objc/runtime.h>
//#import "FMDB.h"


@implementation HJSQLDataTool
{
    FMDatabaseQueue *_fmdbQuen;
}

+ (instancetype)sharedManager
{
    static HJSQLDataTool * manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!manager)
        {
            manager = [[HJSQLDataTool alloc] initPrivate];
        }
    });
    return manager;
}

- (instancetype)initPrivate
{
    
    self = [super init];
    if (self) {
        [self createDB];
    }
    return self;
    
}

- (instancetype)init
{
    
    NSAssert(FALSE, @"HJSQLDataTool 不能调用init创建对象，请使用单例方法获取。");
    
    return nil;
}

#pragma mark - 数据库相关操作
// 创建数据库
- (void)createDB
{
    // 参数1：找的目录名称
    // 参数2：在哪儿找
    // 参数3：是否展开波浪号
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
    NSLog(@"documents path = %@", documentsPath);
    NSString * dbPath = [documentsPath stringByAppendingPathComponent:@"LYGaiWo.sqlite"];
    // 创建DB管理对象
    _fmdbQuen = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    
}

#pragma mark - 创建表
- (BOOL)createTableFromClass:(Class)objcClass
{
    // 获取Class的name
    NSString * tableName = NSStringFromClass(objcClass);
    
    // 获取class的属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    // SQLite数据库，无类型数据库
    
    // 拼接字段
    NSString * propertiesStr = [propertiesArray componentsJoinedByString:@" TEXT, "];
    propertiesStr = [propertiesStr stringByAppendingString:@" TEXT"];
    
    
    
    NSString * createSql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@);", tableName,propertiesStr];
    
    NSLog(@"createSql = %@", createSql);
    
    __block BOOL isSuccess = NO;
    // 执行SQL
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:createSql];
        
        NSLog(@"createSql %@",isSuccess == YES ? @"成功" : @"失败");
        
    }];
    
    return isSuccess;
}

- (BOOL)createTableWithTableName:(NSString *)tableName class:(Class)objcClass
{
    
    // 获取class的属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    // SQLite数据库，无类型数据库
    
    // 拼接字段
    NSString * propertiesStr = [propertiesArray componentsJoinedByString:@" TEXT, "];
    propertiesStr = [propertiesStr stringByAppendingString:@" TEXT"];
    
    
    
    NSString * createSql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@);", tableName,propertiesStr];
    
    NSLog(@"createSql = %@", createSql);
    
    __block BOOL isSuccess = NO;
    // 执行SQL
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:createSql];
        
        NSLog(@"createSql %@",isSuccess == YES ? @"成功" : @"失败");
        
    }];
    
    return isSuccess;
}

- (BOOL)isTableExists:(Class)cls
{
    __block BOOL isExis = NO;
    NSString *tableName = NSStringFromClass(cls);
    NSString *queryCreateSqlStr = [NSString stringWithFormat:@"select sql from sqlite_master where type = 'table' and name = '%@'", tableName];
    
    
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet * resultSet = [db executeQuery:queryCreateSqlStr];
        while ([resultSet next])
        {
            isExis = YES;
        }
    }];
    
    return isExis;
}


#pragma mark - 查询数据是否存在
// 对象全属性判断数据是否已存在
- (BOOL)isExistWithObject:(id)object
{
    // 获取class
    Class objcClass = [object class];
    // 获取表名
    NSString * tableName = NSStringFromClass(objcClass);
    
    // 获取属性列表
    NSArray * propArray = [self getPropertiesFromClass:objcClass];
    // 获取值列表
    NSArray * valueArray = [self getValuesFromObject:object];
    
    // 拼接Where子查询语句
    NSString * whereStr = [propArray componentsJoinedByString:@"=? AND "];
    // appId=? AND appName=? AND appImage
    whereStr = [whereStr stringByAppendingString:@"=?"];
    
    // 查找对象，全属性判断
    NSString * selectSql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", tableName, whereStr];
    NSLog(@"selectSql = %@", selectSql);
    // 执行查找语句
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        
        FMResultSet * resultSet = [db executeQuery:selectSql withArgumentsInArray:valueArray];
        while ([resultSet next])
        {
            isSuccess = YES;
        }
        
    }];
    
    NSLog(@"sql 全属性查询操作 %@",isSuccess == YES ? @"成功" : @"失败");
    
    return isSuccess;
}
// 对象全属性判断数据是否已存在
- (BOOL)isExistWithTableName:(NSString *)tableName  Object:(id)object
{
    // 获取class
    Class objcClass = [object class];
    // 获取表名
    //    NSString * tableName = NSStringFromClass(objcClass);
    
    // 获取属性列表
    NSArray * propArray = [self getPropertiesFromClass:objcClass];
    // 获取值列表
    NSArray * valueArray = [self getValuesFromObject:object];
    
    // 拼接Where子查询语句
    NSString * whereStr = [propArray componentsJoinedByString:@"=? AND "];
    // appId=? AND appName=? AND appImage
    whereStr = [whereStr stringByAppendingString:@"=?"];
    
    // 查找对象，全属性判断
    NSString * selectSql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", tableName, whereStr];
    NSLog(@"selectSql = %@", selectSql);
    // 执行查找语句
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet * resultSet = [db executeQuery:selectSql withArgumentsInArray:valueArray];
        while ([resultSet next])
        {
            isSuccess = YES;
        }
        
    }];
    
    NSLog(@"sql 全属性查询操作 %@",isSuccess == YES ? @"成功" : @"失败");
    
    return isSuccess;
}

// 对象某个属性判断数据是否已存在
- (BOOL)isExistWithTableName:(NSString *)tableName key:(NSString *)key value:(NSString *)value
{
    if (tableName.length == 0 || key.length == 0 || value.length == 0)
    {
        NSLog(@"对象相关属性出错, 无法查询 tableName = %@ key = %@ value = %@",tableName,key,value);
        return NO;
    }
    // 查找对象，单个属性判断
    NSString * selectSql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ = %@", tableName, key , value];
    NSLog(@"selectSql = %@", selectSql);
    // 执行查找语句
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet * resultSet = [db executeQuery:selectSql];
        while ([resultSet next])
        {
            isSuccess = YES;
        }
        
    }];
    
    NSLog(@"sql 单个查询操作 %@",isSuccess == YES ? @"成功" : @"失败");
    
    return isSuccess;
}
#pragma mark - 查询相关数据
/** 查询某表中所有数据, 返回对象数组
 ** 注意:类名和表名必须一致
 */
- (NSArray *)getAllObjectsFromClass:(Class)objcClass
{
    // 获取表名
    NSString * tableName = NSStringFromClass(objcClass);
    
    if (tableName.length == 0)
    {
        NSLog(@"sql 查询数据出错, tableName = %@",tableName);
        return @[];
    }
    
    // 属性名称 -> 类型 dic
    NSDictionary *nameTypeDic = [self classIvarNameTypeDic:objcClass];
    
    NSString * selectAllSql = [NSString stringWithFormat:@"SELECT * FROM %@", tableName];
    
    __block NSMutableArray * objectsArray = @[].mutableCopy;
    
    // 执行SQL返回结果集
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet *resultSet = [db executeQuery:selectAllSql];
        
        
        NSArray * propArray = [self getPropertiesFromClass:objcClass];
        
        while ([resultSet next])
        {
            id object = [[objcClass alloc] init];
            
            for (NSString *prop in propArray)
            {
                id value = [resultSet objectForColumn:prop];
                NSString *type = nameTypeDic[prop];
                if ([type isEqualToString:@"NSArray"] || [type isEqualToString:@"NSDictionary"])
                {
                    // 字符串 ->
                    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
                    value = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
                    
                }else if ([type isEqualToString:@"NSMutableArray"] || [type isEqualToString:@"NSMutableDictionary"])
                {
                    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
                    value = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                }
                
                [object setValue:value forKey:prop];
            }
            
            [objectsArray addObject:object];
        }
        
    }];
    
    return objectsArray.copy;
}

/** 查询某表中所有数据, 根据类返回对象数组*/
- (NSArray *)getAllObjectsFromTableName:(NSString *)tableName objcClass:(Class)objcClass
{
    
    if (tableName.length == 0)
    {
        NSLog(@"sql 查询数据出错, tableName = %@",tableName);
        return @[];
    }
    
    NSString * selectAllSql = [NSString stringWithFormat:@"SELECT * FROM %@", tableName];
    
    __block NSMutableArray * objectsArray = @[].mutableCopy;
    
    // 执行SQL返回结果集
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet *resultSet = [db executeQuery:selectAllSql];
        
        
        NSArray * propArray = [self getPropertiesFromClass:objcClass];
        
        while ([resultSet next])
        {
            id object = [[objcClass alloc] init];
            
            for (NSString *prop in propArray)
            {
                id value = [resultSet objectForColumn:prop];
                
                if (![value isKindOfClass:[NSNull class]] && value != nil)
                {
                    [object setValue:value forKey:prop];
                }
            }
            
            [objectsArray addObject:object];
        }
        
    }];
    
    return objectsArray.copy;
}

/** 根据条件查询某表中所有数据, 根据类返回对象数组
 **parament : 多个查询条件
 **sort : (sort 为空时不排序,  升序:ASC 降序:DESC)
 */
- (NSArray *)getAllObjectsFromTableName:(NSString *)tableName objcClass:(Class)objcClass parament:(NSDictionary *)parament sort:(NSString *)sort
{
    
    if (tableName.length == 0)
    {
        NSLog(@"sql 查询数据出错, tableName = %@",tableName);
        return @[];
    }
    
    if (parament == nil || ![parament isKindOfClass:[NSDictionary class]])
    {
        NSLog(@"sql 查询数据出错, tableName = %@ ",tableName);
        return @[];
    }
    
    NSMutableString *whereStr = @"".mutableCopy;
    for (NSString *key in parament)
    {
        [whereStr appendString:[NSString stringWithFormat:@"%@ = %@ AND ",key, parament[key]]];
    }
    
    NSLog(@"sql 拼接查询语句str = %@",whereStr);
    if (whereStr.length > 5)
    {
        whereStr = [whereStr substringToIndex:whereStr.length - 5].mutableCopy;
    }
    NSLog(@"sql 拼接查询语句str = %@",whereStr);
    
    
    NSString * selectAllSql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", tableName,whereStr];
    
    if (sort.length != 0)
    {
        if ([sort isEqualToString:@"ASC"] || [sort isEqualToString:@"DESC"])
        {
            selectAllSql = [NSString stringWithFormat:@"%@ ORDER BY sort %@;",selectAllSql,sort];
        }else
        {
            NSLog(@"sql 查询排序参数错误 sort = %@", sort);
        }
    }
    
    
    __block NSMutableArray * objectsArray = @[].mutableCopy;
    
    // 执行SQL返回结果集
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet *resultSet = [db executeQuery:selectAllSql];
        
        
        NSArray * propArray = [self getPropertiesFromClass:objcClass];
        
        while ([resultSet next])
        {
            id object = [[objcClass alloc] init];
            
            for (NSString *prop in propArray)
            {
                id value = [resultSet objectForColumn:prop];
                
                [object setValue:value forKey:prop];
            }
            
            [objectsArray addObject:object];
        }
        
    }];
    
    return objectsArray.copy;
}

/** 返回表中某个属性所有值的数组*/
- (NSArray *)getAllValuesFromTableName:(NSString *)tableName WithKey:(NSString *)key
{
    
    if (tableName.length == 0 || key.length == 0)
    {
        NSLog(@"sql 查询数据出错, tableName = %@ parament = %@",tableName,key);
        return @[];
    }
    
    
    NSString * selectAllSql = [NSString stringWithFormat:@"SELECT %@ FROM %@;", key,tableName];
    
    __block NSMutableArray * objectsArray = @[].mutableCopy;
    
    // 执行SQL返回结果集
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        FMResultSet *resultSet = [db executeQuery:selectAllSql];
        
        //        NSArray * propArray = [self getPropertiesFromClass:objcClass];
        
        while ([resultSet next])
        {
            
            NSString *str = [resultSet stringForColumnIndex:0];
            
            [objectsArray addObject:str];
        }
        
    }];
    
    return objectsArray.copy;
    
}

#pragma mark - 更新相关


- (BOOL)upDateWithTableName:(NSString *)tableName upParament:(NSDictionary *)upParament matchParament:(NSDictionary *)matchParament
{
    if (tableName.length == 0 || ![upParament isKindOfClass:[NSDictionary class]] || ![matchParament isKindOfClass:[NSDictionary class]] || upParament.count == 0 || matchParament.count == 0)
    {
        NSLog(@"sql 更新表中相关字段出错 tableName = %@",tableName);
        return NO;
    }
    
    NSString *upSql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = %@ WHERE %@ = %@;",tableName,upParament.allKeys.firstObject,upParament.allValues.firstObject,matchParament.allKeys.firstObject,matchParament.allValues.firstObject];
    NSLog(@"upsql = %@",upSql);
    __block BOOL isSuccess = NO;
    
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:upSql];
        
    }];
    
    // [db executeUpdate:@"UPDATE t_student SET score = 1500 WHERE name = 'zs';"];
    //    [_fmdbQuen inTransaction:^(FMDatabase *db, BOOL *rollback) {
    //
    //         [db executeUpdate:upSql];
    //
    //
    //    }];
    
    NSLog(@"sql  更新 %@", isSuccess == YES ? @"成功" : @"失败");
    
    return isSuccess;
}

// 添加数据
- (BOOL)insertTableWithObject:(id)object
{
    // 全属性判断是否已存在
    //    if ([self isExistWithObject:object]) {
    //        return NO;
    //    }
    
    // 获取对象的class
    Class objcClass = [object class];
    
    //判断是否创建表, 如果没有创建, 创建表
    if (![self isTableExists:objcClass])
    {
        [self createTableFromClass:objcClass];
    }
    
    
    // 获取类名
    NSString * tableName = NSStringFromClass(objcClass);
    
    // 获取属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    NSString * propStr = [propertiesArray componentsJoinedByString:@", "];
    
    // 获取值
    NSArray * valuesArray = [self getValuesFromObject:object];
    
    // 创建问号
    NSMutableArray * placeHolderArray = @[].mutableCopy;
    
    for (NSInteger i = 0; i < propertiesArray.count ; i++)
    {
        [placeHolderArray addObject:@"?"];
    }
    
    
    NSString * placeHolderStr = [placeHolderArray componentsJoinedByString:@", "];
    
    NSString * insertSql = [NSString stringWithFormat:@"INSERT INTO %@  (%@) VALUES (%@);", tableName, propStr, placeHolderStr];
    
    NSLog(@"insertSql = %@", insertSql);
    
    __block BOOL isSuccess = NO;
    
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess =[db executeUpdate:insertSql withArgumentsInArray:valuesArray];
        
        NSLog(@"sql 插入数据 %@", isSuccess == YES ? @"成功" : @"失败");
    }];
    
    return isSuccess;
}

- (BOOL)insertWithTableName:(NSString *)tableName object:(id)object
{
    //    // 全属性判断是否已存在
    //    if ([self isExistWithTableName:tableName Object:object]) {
    //        return NO;
    //    }
    
    // 获取对象的class
    Class objcClass = [object class];
    
    //判断是否创建表, 如果没有创建, 创建表
    if (![self isTableExists:objcClass])
    {
        [self createTableFromClass:objcClass];
    }
    
    
    // 获取属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    NSString * propStr = [propertiesArray componentsJoinedByString:@", "];
    
    // 获取值
    NSArray * valuesArray = [self getValuesFromObject:object];
    
    // 创建问号
    NSMutableArray * placeHolderArray = @[].mutableCopy;
    
    for (NSInteger i = 0; i < propertiesArray.count ; i++)
    {
        [placeHolderArray addObject:@"?"];
    }
    
    
    NSString * placeHolderStr = [placeHolderArray componentsJoinedByString:@", "];
    
    NSString * insertSql = [NSString stringWithFormat:@"INSERT INTO %@  (%@) VALUES (%@);", tableName, propStr, placeHolderStr];
    
    NSLog(@"insertSql = %@", insertSql);
    
    __block BOOL isSuccess = NO;
    
    
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess =[db executeUpdate:insertSql withArgumentsInArray:valuesArray];
        
        NSLog(@"sql 插入数据 %@", isSuccess == YES ? @"成功" : @"失败");
    }];
    
    return isSuccess;
}

- (BOOL)insertTableWithObjects:(NSArray *)objects
{
    
    // 获取对象的class
    Class objcClass = [objects.firstObject class];
    
    //判断是否创建表, 如果没有创建, 创建表
    if (![self isTableExists:objcClass])
    {
        [self createTableFromClass:objcClass];
    }
    
    
    // 获取类名
    NSString * tableName = NSStringFromClass(objcClass);
    
    // 获取属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    NSString * propStr = [propertiesArray componentsJoinedByString:@", "];
    
    NSMutableArray *sqls = @[].mutableCopy;
    NSMutableArray *valus = @[].mutableCopy;
    // 获取值
    for (id obj in objects)
    {
        NSArray * valuesArray = [self getValuesFromObject:obj];
        
        // 创建问号
        NSMutableArray * placeHolderArray = @[].mutableCopy;
        
        for (NSInteger i = 0; i < propertiesArray.count ; i++)
        {
            [placeHolderArray addObject:@"?"];
        }
        
        
        NSString * placeHolderStr = [placeHolderArray componentsJoinedByString:@", "];
        
        NSString * insertSql = [NSString stringWithFormat:@"INSERT INTO %@  (%@) VALUES (%@);", tableName, propStr, placeHolderStr];
        
        [sqls addObject:insertSql];
        [valus addObject:valuesArray];
    }
    
    __block BOOL isSuccess = NO;
    
    [_fmdbQuen inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
        
        for (NSInteger i = 0; i < sqls.count; i ++)
        {
            isSuccess =[db executeUpdate:sqls[i] withArgumentsInArray:valus[i]];
        }
        
        if (isSuccess == NO)
        {
            *rollback  = YES;
            return;
        }
    }];
    return isSuccess;
}

- (BOOL)insertWithTableName:(NSString *)tableName Objects:(NSArray *)objects
{
    // 获取对象的class
    Class objcClass = [objects.firstObject class];
    
    //判断是否创建表, 如果没有创建, 创建表
    if (![self isTableExists:[tableName class]])
    {
        [self createTableWithTableName:tableName class:[objects.firstObject class]];
    }
    
    
    // 获取属性列表
    NSArray * propertiesArray = [self getPropertiesFromClass:objcClass];
    NSString * propStr = [propertiesArray componentsJoinedByString:@", "];
    
    NSMutableArray *sqls = @[].mutableCopy;
    NSMutableArray *valus = @[].mutableCopy;
    // 获取值
    for (id obj in objects)
    {
        NSArray * valuesArray = [self getValuesFromObject:obj];
        
        // 创建问号
        NSMutableArray * placeHolderArray = @[].mutableCopy;
        
        for (NSInteger i = 0; i < propertiesArray.count ; i++)
        {
            [placeHolderArray addObject:@"?"];
        }
        
        
        NSString * placeHolderStr = [placeHolderArray componentsJoinedByString:@", "];
        
        NSString * insertSql = [NSString stringWithFormat:@"INSERT INTO %@  (%@) VALUES (%@);", tableName, propStr, placeHolderStr];
        
        [sqls addObject:insertSql];
        [valus addObject:valuesArray];
    }
    
    __block BOOL isSuccess = NO;
    
    [_fmdbQuen inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
        
        for (NSInteger i = 0; i < sqls.count; i ++)
        {
            isSuccess =[db executeUpdate:sqls[i] withArgumentsInArray:valus[i]];
        }
        
        if (isSuccess == NO)
        {
            *rollback  = YES;
            return;
        }
    }];
    return isSuccess;
}



#pragma mark - 删除相关
- (BOOL)deleteTableName:(NSString *)tableName
{
    if (tableName.length == 0)
    {
        NSLog(@"删除表失败, tableName为空");
        return NO;
    }
    
    NSString * deleteSql = [NSString stringWithFormat:@"DELETE FROM %@", tableName];
    
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:deleteSql];
        
        NSLog(@"删除表操作  %@",isSuccess == YES ? @"成功" : @"失败");
        
    }];
    
    return isSuccess;
}

- (BOOL)deleteDataFromeTable:(NSString *)tableName WithKey:(NSString *)key value:(NSString *)value
{
    if (tableName.length == 0 || key.length == 0 || value.length == 0)
    {
        NSLog(@"删除表失败, tableName = %@ key = %@ value = %@",tableName,key,value);
        return NO;
    }
    
    NSString * deleteSql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE %@ = '%@'", tableName,key,value];
    
    NSLog(@"deleteSql = %@",deleteSql);
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:deleteSql];
        
        NSLog(@"删除表操作  %@",isSuccess == YES ? @"成功" : @"失败");
        
    }];
    
    return isSuccess;
}

- (BOOL)deleteDataFromeTable:(NSString *)tableName WithParaments:(NSDictionary *)paraments
{
    if (tableName.length == 0 || ![paraments isKindOfClass:[NSDictionary class]] || paraments.count == 0)
    {
        NSLog(@"删除表失败, tableName = %@ ",tableName);
        return NO;
    }
    
    NSMutableString *deleteStr = @"".mutableCopy;
    
    if ([paraments isKindOfClass:[NSDictionary class]] && paraments.count > 0)
    {
        for (NSString *key in paraments)
        {
            [deleteStr appendString:[NSString stringWithFormat:@" %@ = %@ AND",key,paraments[key]]];
        }
    }
    
    if (deleteStr.length > 4)
    {
        deleteStr = [deleteStr substringToIndex:deleteStr.length - 3].mutableCopy;
    }
    
    NSLog(@"sql deleteStr = %@", deleteStr);
    
    NSString * deleteSql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE %@", tableName,deleteStr];
    
    __block BOOL isSuccess = NO;
    [_fmdbQuen inDatabase:^(FMDatabase * _Nonnull db) {
        
        isSuccess = [db executeUpdate:deleteSql];
        
        NSLog(@"删除表操作  %@",isSuccess == YES ? @"成功" : @"失败");
        
    }];
    
    return isSuccess;
}


#pragma mark - 运行时
// 获取一个类的所有属性
// 用这个方法只能获取属性, 不能获取成员变量, 且, 如果类有遵循协议, 会获取多的成员变量, 需要底层技术, 目前不懂
//- (NSArray *)getPropertiesFromClass:(Class)class
//{
//    // 创建数组存储所有属性
//    NSMutableArray * propertiesArray = [NSMutableArray array];
//
//    unsigned int propertiescount = 0;
//    // 通过runtime获取类中所有的属性
//    // 参数1：class
//    // 参数2：属性的个数
//    // 返回值：指针，指向一个数组，指向数组中第一个元素
//    objc_property_t * objcPropertyArray =  class_copyPropertyList(class, &propertiescount);
//    // 循环遍历取出属性
//    for (int idx = 0; idx < propertiescount; idx++)
//    {
//        objc_property_t property = objcPropertyArray[idx];
//        // 获取结构中属性的name
//        const char * propertyName = property_getName(property);
//        // 将char * 转换为NSString
//        NSString * nameStr = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
//        // 添加到数组中
//        [propertiesArray addObject:nameStr];
//    }
//
//    return propertiesArray;
//}


- (NSArray *)getPropertiesFromClass:(Class)class
{
    // 获取这个类, 里面, 所有的成员变量以及类型
    unsigned int outCount = 0;
    Ivar *varList = class_copyIvarList(class, &outCount);
    
    //创建数组存储所有属性
    NSMutableArray * propertiesArray = [NSMutableArray array];
    NSArray *ignoreNames = nil;
//    if ([class respondsToSelector:@selector(ignoreColumnNames)])
//    {
//        ignoreNames = [class ignoreColumnNames];
//    }
    
    for (int i = 0; i < outCount; i++)
    {
        Ivar ivar = varList[i];
        
        // 1. 获取成员变量名称
        NSString *ivarName = [NSString stringWithUTF8String: ivar_getName(ivar)];
        if ([ivarName hasPrefix:@"_"])
        {
            ivarName = [ivarName substringFromIndex:1];
        }
        
        
        if([ignoreNames containsObject:ivarName])
        {
            continue;
        }
        
        [propertiesArray addObject:ivarName];
    }
    
    return propertiesArray;
    
}

// 获取一个对象的所有属性值
- (NSArray *)getValuesFromObject:(id)object
{
    // 创建数组存储所有的值
    NSMutableArray * valuesArray = [NSMutableArray array];
    // 先获取所有的属性
    NSArray * propArray = [self getPropertiesFromClass:[object class]];
    for (NSString * prop in propArray)
    {
        // 通过KVC方式获取对象中的值
        id value = [object valueForKey:prop];
        if (!value)
        {
            [valuesArray addObject:[NSNull null]];
            // nil NSNull 区别
        }else
        {
            if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]])
            {
                // 在这里, 把字典或者数组, 处理成为一个字符串, 保存到数据库里面去
                // 字典/数组 -> data
                NSData *data = [NSJSONSerialization dataWithJSONObject:value options:NSJSONWritingPrettyPrinted error:nil];
                // data -> nsstring
                value = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            }
            [valuesArray addObject:value];
        }
    }
    return valuesArray;
}

/** 对外暴露的fmdbQuen 如果遇到特殊业务不好封装时用 */
- (void)exposeWithBlk:(void (^)(FMDatabaseQueue * fmdbQuen))blk;
{
    //    NSLog(@"%@",_fmdbQuen);
    if (blk)
    {
        blk(_fmdbQuen);
    }
    
}

/**
 所有的有效成员变量, 以及成员变量对应的类型
 // 有效的成员变量名称, 以及, 对应的类型
 @param cls 类名
 @return 所有的有效成员变量, 以及成员变量对应的类型
 */
- (NSDictionary *)classIvarNameTypeDic:(Class)cls {
    
    // 获取这个类, 里面, 所有的成员变量以及类型
    
    unsigned int outCount = 0;
    Ivar *varList = class_copyIvarList(cls, &outCount);
    
    NSMutableDictionary *nameTypeDic = [NSMutableDictionary dictionary];
    
    NSArray *ignoreNames = nil;
//    if ([cls respondsToSelector:@selector(ignoreColumnNames)]) {
//        ignoreNames = [cls ignoreColumnNames];
//    }
    
    
    
    for (int i = 0; i < outCount; i++) {
        Ivar ivar = varList[i];
        
        // 1. 获取成员变量名称
        NSString *ivarName = [NSString stringWithUTF8String: ivar_getName(ivar)];
        if ([ivarName hasPrefix:@"_"]) {
            ivarName = [ivarName substringFromIndex:1];
        }
        
        
        if([ignoreNames containsObject:ivarName]) {
            continue;
        }
        
        // 2. 获取成员变量类型
        NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        
        type = [type stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"@\""]];
        
        
        [nameTypeDic setValue:type forKey:ivarName];
    }
    
    return nameTypeDic;
    
}

@end
